package com.ubo.uspeed;

import java.io.FileOutputStream;

import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;

public class Visiteur {

	/**
	 * Racine du fichier XML
	 */
	protected Element racine;

	/**
	 * Document permettant la création du fichier XML
	 */
	protected Document document;
	/**
	 * Element courant
	 */
	 protected Element current;

	/**
	 * Constructeur
	 */
	public Visiteur() {
		racine = new Element("SchemaUML");

		/**
		 * Document permettant la création du fichier XML
		 */
		document = new Document(racine);

		/**
		 * Element courant
		 */
		 current = racine;
	}

	/**
	 * Ajout une methode du métamodele au fichier xml
	 * 
	 * @param m
	 */
	public void visitMethode(Methode m) {
		Element saveC = current;
		Element method = new Element("Methode");
		method.setAttribute(new Attribute("name", m.getmName()));
		if (m.getmType() != null)
			method.setAttribute(new Attribute("type", m.getmType().toString()
					.toLowerCase()));
		if (m.getmVis() != null)
			method.setAttribute(new Attribute("visibility", "" + m.getmVis()));
		if (m.getmMod() != null)
			method.setAttribute(new Attribute("modifier", "" + m.getmMod()));
		current.addContent(method);
		current = method;
		for (int i = 0; i < m.getListA().size(); i++) {
			m.getListA().get(i).accept(this);
		}
		current = saveC;
	}

	/**
	 * Ajout une note du métamodele au fichier xml
	 * 
	 * @param n
	 */
	public void visitNotes(Notes n) {
		Element notes = new Element("Notes");
		notes.setAttribute(new Attribute("name", n.getmName()));
		if (n.getmTexte() != null)
			notes.setAttribute(new Attribute("texte", n.getmTexte()));
		current.addContent(notes);
	}

	/**
	 * Ajout un package du métamodele au fichier xml
	 * 
	 * @param p
	 */
	public void visitPackage(UPackage p) {
		Element saveC = current;
		Element upack = new Element("Package");
		upack.setAttribute(new Attribute("name", p.getmName()));
		current.addContent(upack);
		current = upack;
		for (int i = 0; i < p.getListC().size(); i++) {
			p.getListC().get(i).accept(this);
		}
		for (int i = 0; i < p.getListP().size(); i++) {
			p.getListP().get(i).accept(this);
		}
		current = saveC;
	}

	/**
	 * Ajout un classifier du métamodele au fichier xml
	 * 
	 * @param u
	 */
	public void visitClassifier(Classifier u) {
		Element saveC = current;
		Element uclass = new Element("Classifier");
		uclass.setAttribute(new Attribute("name", u.getmName()));
		uclass.setAttribute(new Attribute("type", u.getmType().toString()
				.toLowerCase()));
		if (u.getmVis() != null)
			uclass.setAttribute(new Attribute("visibility", ""
					+ u.getmVis().toString().toLowerCase()));
		if (u.getmMod() != null)
			uclass.setAttribute(new Attribute("modifier", ""
					+ u.getmMod().toString().toLowerCase()));
		current.addContent(uclass);
		current = uclass;
		for (int i = 0; i < u.getListA().size(); i++) {
			u.getListA().get(i).accept(this);
		}
		for (int i = 0; i < u.getListM().size(); i++) {
			u.getListM().get(i).accept(this);
		}
		current = saveC;
	}

	/**
	 * Ajout une association du métamodele au fichier xml
	 * 
	 * @param a
	 */
	public void visitAssociation(Association a) {
		Element assoc = new Element("Association");
		assoc.setAttribute(new Attribute("name", a.getmName()));
		assoc.setAttribute(new Attribute("source", a.getmSource().getmName()));
		assoc.setAttribute(new Attribute("destination", a.getmDestination()
				.getmName()));
		assoc.setAttribute(new Attribute("type", a.getmType().toString()
				.toLowerCase()));
		assoc.setAttribute(new Attribute("cardSource", a.getmSCard()));
		assoc.setAttribute(new Attribute("cardDest", a.getmDCard()));
		racine.addContent(assoc);
	}

	/**
	 * Ajout un attribut du métamodele au fichier xml
	 * 
	 * @param a
	 */
	public void visitAttribute(UAttribute a) {
		Element attrib = new Element("Attribute");
		attrib.setAttribute(new Attribute("name", a.getmName()));
		if (a.getmType() != null)
			attrib.setAttribute(new Attribute("type", a.getmType().toString()
					.toLowerCase()));
		if (a.getmVis() != null)
			attrib.setAttribute(new Attribute("visibility", "" + a.getmVis()));
		if (a.getmMod() != null)
			attrib.setAttribute(new Attribute("modifier", "" + a.getmMod()));
		current.addContent(attrib);
	}

	/**
	 * explore le métamodele pour l'ajout au fichier xml
	 * 
	 * @param s
	 */
	public void visitSchemaUML(SchemaUML s) {
		for (int i = 0; i < s.getListPackage().size(); i++) {
			s.getListPackage().get(i).accept(this);
		}
		for (int i = 0; i < s.getListNotes().size(); i++) {
			s.getListNotes().get(i).accept(this);
		}
		for (int i = 0; i < s.getListAssociation().size(); i++) {
			s.getListAssociation().get(i).accept(this);
		}
	}

	/**
	 * Affiche le document xml obtenue
	 */
	public void affiche() {
		try {
			// On utilise ici un affichage classique avec getPrettyFormat()
			XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
			sortie.output(document, System.out);
		} catch (java.io.IOException e) {
		}
	}

	public String getOuput() {
		XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
		return sortie.outputString(document);
	}

	/**
	 * Créaiton du fichier xml
	 * 
	 * @param fichier
	 */
	public void generateXML(String fichier) {
		try {
			// On utilise ici un affichage classique avec getPrettyFormat()
			XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat());
			// Remarquez qu'il suffit simplement de cr�er une instance de
			// FileOutputStream
			// avec en argument le nom du fichier pour effectuer la
			// s�rialisation.
			sortie.output(document, new FileOutputStream(fichier));
		} catch (java.io.IOException e) {
		}
	}
}
